package wcg;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Iterator;
import java.util.LinkedList;


import ikelib.byteUtil;
import ikelib.wintime;

/*
 * いろいろなデータからWinファイルを作る
 */
public class WinImporter {
	public WinImporter(){
		
	}
	/*
	 * 
	 */
	private LinkedList<byte[]> makeWinData(ImportData data){
		int count = data.GetChCount();
		int[] chid = data.GetId();
		
		int[] indexes = new int[count];
		for(int i=0;i<indexes.length;i++) indexes[i] = 0;
		
		wintime wt = data.GetWinTime();
		int span = data.GetSpan();
		
		LinkedList<byte[]> datalist = new LinkedList<byte[]>();
		int totallen=0;
		for(int j=0;j<span;j++){
			int dlen = 0;
			byte[] blkhd = new byte[4];
			dlen += blkhd.length;
			datalist.add(blkhd);
			byte[] bcd = wt.getBcd();
			dlen += bcd.length;
			datalist.add(bcd);
			for(int i=0;i<chid.length;i++){
				int id = chid[i];
				int sr = data.GetSamplerate(id);
				int[] dt = data.GetData(id);
				int[] tmp = new int[sr];
				System.arraycopy(dt, indexes[i], tmp, 0, sr);
				indexes[i]+=sr;
				byte[] chblock = makeChannelBlockData(id,tmp);
				dlen += chblock.length;
				datalist.add(chblock);
			}
			byteUtil.conv4Byte(dlen,blkhd,0);
			totallen+=dlen;
			wt.inc_sec();
		}
		
		return datalist;	
	}
	public String makeWinFile(String outfilename,ImportData data){
		LinkedList<byte[]> dl = makeWinData(data);
		File of = new File(outfilename);
		
		FileOutputStream os;
		BufferedOutputStream bos;
		try {
			bos = new BufferedOutputStream(new FileOutputStream(of));
			Iterator<byte[]> ite = dl.iterator();
			while(ite.hasNext()){
				byte[] b = ite.next();
				bos.write(b);
			}
			bos.flush();
			bos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		} 
		return outfilename;
	}
	
	/*
	 * チャンネルブロックデータを作成する。
	 * rdは１秒分のデータ
	 */
	private byte[] makeChannelBlockData(int channelID,int[] rd){
		int max = 0x80000000;
		int min = 0x7fffffff;
		for(int i=0;i<rd.length-1;i++){
			int delta = rd[i+1]-rd[i];
			if(max < delta) max = delta;
			if(min > delta) min = delta;
		}
		int enc ;
		if(max > 0x7fffff || min < -0x800000)  enc = 4;
		else if(max > 0x7fff || min < -0x8000) enc = 3;
		else if(max > 0x7f || min < -0x80) enc = 2;
		else if(max > 0x7 || min < -0x8) enc = 1;
		else enc = 0;
		int dlength;
		if(enc == 0) dlength = 4 + (rd.length) / 2; 		// 4=channel header
		else         dlength = 4 + (rd.length -1)*enc;
		
		
		byte[] ret = new byte[dlength+4];
		byteUtil.conv2UByte(channelID,ret,0);
		int encandlen = (rd.length & 0xfff) | (enc<<12) & 0xf000;
		byteUtil.conv2UByte(encandlen,ret,2);
		
		int index = 0;
		byteUtil.conv4Byte(rd[index],ret,4);
		index++;
		for(int bi=4+4;index<rd.length;index++){
			switch(enc){
			case 4: 
				byteUtil.conv4Byte(rd[index] - rd[index-1], ret, bi);
				bi += 4;
				break;
			case 3: 
				byteUtil.conv3Byte(rd[index] - rd[index-1], ret, bi);
				bi += 3;
				break;
			case 2: 
				byteUtil.conv2Byte(rd[index]- rd[index-1], ret, bi);
				bi += 2;
				break;
			case 1: 
				byteUtil.convByte(rd[index]  - rd[index-1], ret, bi);
				bi += 1;
				break;
			case 0: 
				byteUtil.convHalfByte(rd[index]  - rd[index-1], ret, bi,false);
				index++;
				if(rd.length>index) byteUtil.convHalfByte(rd[index]  - rd[index-1], ret, bi,true);
				bi += 1;
				break;
			}
		}
		return ret;
	}
	
	
}
